/*******************************************************************************
 * Copyright (c) 2010, 2017 西安秦晔信息科技有限公司
 * Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *******************************************************************************/
package com.qinyeit.serviceapp.service.organization.impl;

import com.google.common.collect.Lists;
import com.qinyeit.serviceapp.entity.*;
import com.qinyeit.serviceapp.entity.enums.CommentType;
import com.qinyeit.serviceapp.entity.enums.PaymentType;
import com.qinyeit.serviceapp.exception.BusinessRunTimeException;
import com.qinyeit.serviceapp.service.auxiliary.CommentService;
import com.qinyeit.serviceapp.service.pays.PaymentService;
import com.qinyeit.serviceapp.utils.SearchUtils;
import com.qinyetech.springstage.core.entity.search.Searchable;
import com.qinyetech.springstage.core.lang.QyMap;
import com.qinyetech.springstage.core.repository.jdbc.PageNamedParameterJdbcTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 商户端初始化数据
 */
@Slf4j
@Service
public class MerchantInitServiceImpl {

    @Resource(name = "branchJdbcTemplate")
    private PageNamedParameterJdbcTemplate branchJdbcTemplate;
    @Autowired
    private PageNamedParameterJdbcTemplate jdbcTemplate;
    private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private CommentService commentService;


    /**
     * 同步总部的原因备注
     * @param merchantId
     * @param merchantGroupId
     */
    void updateComment(Long merchantId,Long merchantGroupId){
        //删除分店的原因备注
        String sql = "DELETE from comments where merchant_id = :merchantId";
        QyMap map = QyMap.map("merchantId",merchantId);
        branchJdbcTemplate.update(sql,map);
        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("sys_eq",true);
        List<Comment> commentList = commentService.findWithSort(searchable);
        if(CollectionUtils.isNotEmpty(commentList)){
            Map<String,?>[] maps = new Map[commentList.size()];
            QyMap params = null;
            int index = 0;
            for (Comment comment : commentList) {
                CommentState state = null;
                if(comment.getType()== CommentType.FANJIE){
                    state = CommentState.THECHECKOUT;
                }else if(comment.getType()==CommentType.KOUWEI){
                    state = CommentState.TASTE;
                }else if (comment.getType()==CommentType.MIANDAN){
                    state = CommentState.FREEOFCHARGE;
                }else if (comment.getType()==CommentType.TUICAI){
                    state=CommentState.FOODBACK;
                }else if (comment.getType()==CommentType.WAIMAIQUXIAO){
                    state = CommentState.TAKEOUT;
                }else if (comment.getType()==CommentType.ZENGCAI){
                    state=CommentState.GIVEFOOD;
                }else if(comment.getType()==CommentType.ZHEKOU){
                    state=CommentState.DISCOUNT;
                }

                params = QyMap.map("deleted",comment.isDeleted())
                        .setv("merchantId",merchantId)
                        .setv("name",comment.getName())
                        .setv("type",state.getKey())
                        .setv("sys",comment.getSys())
                        .setv("uuid",comment.getUuid())
                        .setv("update_timestamp",comment.getUpdateTimestamp());
                maps[index] = params;
                index++;
            }
            sql = "INSERT INTO comments (create_at,is_deleted,status,merchant_id,name,type,sys,uuid,update_timestamp) " +
                    "values(NOW(),:deleted,0,:merchantId,:name,:type,:sys,:uuid,:update_timestamp)";
            branchJdbcTemplate.batchUpdate(sql,maps);
        }
    }

    /**
     * 修改单店的数据
     * @param branch
     * @param merchantGroup
     */
    public void updateBranchData(Branch branch, MerchantGroup merchantGroup,Long merchantId,boolean isEdit) {
        String sql = "";
        QyMap map ;
        if(isEdit && StringUtils.isNotBlank(branch.getPassword())){
            sql = "SELECT * from merchant_accounts where is_deleted=0 and is_admin = 1 and merchant_id = :merchantId";
            map = QyMap.map("merchantId",merchantId);
            List<Map<String,Object>> list = branchJdbcTemplate.queryForList(sql,map);
            if(CollectionUtils.isNotEmpty(list)){
                QyMap passworddigist = getPasswordDigist(branch.getUsername(),branch.getPassword());
                sql = "update merchant_accounts set password_digist=:passwordDigist,salt=:salt where id=:id";
                map = QyMap.map("passwordDigist",passworddigist.getString("newPassword"))
                        .setv("salt",passworddigist.getString("salt"))
                        .setv("id",list.get(0).get("id"));
                branchJdbcTemplate.update(sql,map);
            }
        }

        sql="update merchants set address=:address,industry=:industry,name=:name,linker=:linker," +
                "phone=:phone,tel_phone=:tel_phone,district=:district,merchant_group_name=:merchant_group_name\n" +
                "where id = :id\n";
        map = QyMap.map("address",branch.getAddress())
                .setv("industry",branch.getIndustry())
                .setv("name",branch.getName())
                .setv("linker",branch.getLinker())
                .setv("phone",branch.getPhone())
                .setv("tel_phone",branch.getTelephone())
                .setv("district",branch.getLocation())
                .setv("merchant_group_name",merchantGroup.getCompanyName())
                .setv("id",merchantId);
        branchJdbcTemplate.update(sql,map);
    }

    public enum CommentState {
        TASTE("口味"),
        FOODBACK("退菜原因"),
        GIVEFOOD("赠菜原因"),
        THECHECKOUT("反结账原因"),
        FREEOFCHARGE("免单原因"),
        TAKEOUT("外卖取消原因"),
        DISCOUNT("折扣原因");

        private final String text;

        private CommentState(String text) {
            this.text = text;
        }
        public String getText() {
            return text;
        }
        public String getKey() {
            return toString();
        }
    }

    /**
     * 同步总部的支付方式
     * @param merchantId
     * @param merchantGroupId
     */
    void updatePayment(Long merchantId,Long merchantGroupId){
        //删除分店的支付方式
        String sql = "DELETE from payment_types where merchant_id = :merchantId";
        QyMap map = QyMap.map("merchantId",merchantId);
        branchJdbcTemplate.update(sql,map);
        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("deleteAble_eq",false);
        List<Payment> paymentList = paymentService.findWithSort(searchable);
        if(CollectionUtils.isNotEmpty(paymentList)){
            Map<String,?>[] maps = new Map[paymentList.size()];
            QyMap params = null;
            int index = 0;
            for (Payment payment : paymentList) {
                PayType payType = null;
                if(payment.getType()==PaymentType.CASH){
                    payType = PayType.CASH;
                }else if(payment.getType()==PaymentType.CASHIER){
                    payType = PayType.SCANBAR;
                }else if (payment.getType()==PaymentType.COUPON){
                    payType = PayType.COUPON;
                }else if (payment.getType()==PaymentType.GUAZHANG){
                    payType=PayType.SUSPENDED;
                }else if (payment.getType()==PaymentType.VIPCARD){
                    payType = PayType.MEMBER;
                }else if (payment.getType()==PaymentType.BANKCARD){
                    payType=PayType.BANKCARD;
                }else if(payment.getType()==PaymentType.THIRDPARTY){
                    payType=PayType.THIRDPARTY;
                }

                params = QyMap.map("deleted",payment.isDeleted())
                        .setv("merchantId",merchantId)
                        .setv("deleteable",payment.getDeleteAble())
                        .setv("hasPoint",payment.getIntegral())
                        .setv("name",payment.getName())
                        .setv("state",payment.getState().getKey())
                        .setv("type",payType.getKey())
                        .setv("remark",payment.getRemark())
                        .setv("recharge",payment.getRecharge())
                        .setv("uuid",payment.getUuid())
                        .setv("update_timestamp",payment.getUpdateTimestamp());
                maps[index] = params;
                index++;
            }
            sql = "INSERT INTO payment_types(create_at,is_deleted,status,merchant_id,delete_able,has_point,name,state,type,remark,recharge,uuid,update_timestamp)\n" +
            "VALUES(NOW(),:deleted,0,:merchantId,:deleteable,:hasPoint,:name,:state,:type,:remark,:recharge,:uuid,:update_timestamp)";
            branchJdbcTemplate.batchUpdate(sql,maps);
        }
    }

    public enum PayType {
        CASH("现金支付"),
        SUSPENDED("挂账支付"),
        MEMBER("会员支付"),
        BANKCARD("银行卡支付"),
        COUPON("优惠券支付"),
        BUYCOUPON("团购支付"),
        THIRDPARTY("其它支付"),
        SCANBAR("悦收银");

        private final String text;

        private PayType(String text) {
            this.text = text;
        }
        public String getText() {
            return text;
        }
        public String getKey() {
            return toString();
        }
    }

    /**
     * 解绑门店 将门店的所有权限分配给门店
     * @param merchantId
     */
    void saveBranchAllPermissions(Long merchantId){
        //根据商户id获取门店管理员角色id
        Long merchantRoleId = getBranchRoleIdByMerchantId(merchantId);
        //删除门店角色权限
        deletedBranchRolePermissionByRoleId(merchantRoleId);
        //保存管理员所有权限
        saveBranchAllPermissionsForMerchant(merchantId,merchantRoleId);
    }

    /**
     * 保存商户所有权限
     * @param merchantId
     * @param merchantRoleId
     */
    private void saveBranchAllPermissionsForMerchant(Long merchantId, Long merchantRoleId) {
        String sql = "SELECT id as permission_id from merchant_permissions";
        List<Map<String,Object>> permissionList = branchJdbcTemplate.queryForList(sql,QyMap.NEW());
        //保存管理员权限
        saveBranchAdminPermissions(permissionList, merchantRoleId);
    }

    /**
     * 分配权限给分店
     * @param merchantId 门店商户id
     * @param roleId 连锁角色id
     */
    void saveBranchPermissions(Long merchantId,Long roleId){
        if (merchantId==null || roleId==null){
            throw new BusinessRunTimeException("数据为空,请检查数据",10001);
        }
        //根据连锁角色id 查询权限id
        String sql = "SELECT permission_id from merchant_role_permissions where role_id = :roleId";
        QyMap params = QyMap.map("roleId",roleId);
        List<Map<String,Object>> permissions = jdbcTemplate.queryForList(sql,params);
//        根据商户id获取门店管理员角色id
        Long merchantRoleId = getBranchRoleIdByMerchantId(merchantId);
//        删除门店角色权限
        deletedBranchRolePermissionByRoleId(merchantRoleId);

        //保存管理员权限
        saveBranchAdminPermissions(permissions, merchantRoleId);

        //将门店其他角色多余的权限删除
        deletedbranchOtherRolePermissions(merchantId,permissions);


    }

    /**
     * 删除商户其他角色多余的权限
     * @param merchantId
     * @param permissions
     */
    private void deletedbranchOtherRolePermissions(Long merchantId,List<Map<String,Object>> permissions) {
        String sql = "DELETE from merchant_role_permissions where \n" +
                "merchant_role_id in(SELECT role_id from cashier_groups where merchant_id = :merchantId) ";
        QyMap params = QyMap.map("merchantId",merchantId);
        if (CollectionUtils.isNotEmpty(permissions)){
            List<Long> permissionIds = Lists.newArrayList();
            for (Map<String, Object> permission : permissions) {
                permissionIds.add(Long.valueOf(permission.get("permission_id").toString()));
            }
            sql += " and (merchant_permission_id not in(:permissions))";
            params.setv("permissions",permissionIds);
        }
        branchJdbcTemplate.update(sql,params);

    }

    /**
     * 保存管理员权限
     * @param permissions 权限串
     * @param merchantRoleId
     */
    private void saveBranchAdminPermissions(List<Map<String, Object>> permissions, Long merchantRoleId) {
        String sql;
        if (CollectionUtils.isNotEmpty(permissions)){
            int index=0;
            for (int i=0;i<permissions.size();i++) {
                if (permissions.get(i).get("permission_id").toString().equals("0")) {
                    continue;
                }
                index++;
            }
            Map<String,?>[] maps = new Map[index];
            QyMap map = null;
            index=0;
            for (int i=0;i<permissions.size();i++) {
                if (permissions.get(i).get("permission_id").toString().equals("0")){
                    continue;
                }
                map = QyMap.map("merchantRoleId",merchantRoleId)
                        .setv("merchantPermissionId",permissions.get(i).get("permission_id"));
                maps[index] = map;
                index++;
            }
            sql = "INSERT merchant_role_permissions (merchant_role_id,merchant_permission_id) " +
                    "VALUES(:merchantRoleId,:merchantPermissionId) ";
            branchJdbcTemplate.batchUpdate(sql,maps);
        }
    }

    /**
     * 根据商户id获取门店管理员角色id
     * @param merchantId
     * @return
     */
    private Long getBranchRoleIdByMerchantId(Long merchantId) {
        String sql;
        QyMap params;//查询门店管理员角色 获取角色id
        sql = "SELECT role_id from cashier_groups where merchant_id = :merchantId and is_admin =1";
        params = QyMap.map("merchantId",merchantId);
        return branchJdbcTemplate.queryForScalar(sql,params,Long.class);
    }

    /**
     * 删除门店角色权限
     * @param merchantRoleId 门店角色
     */
    private void deletedBranchRolePermissionByRoleId(Long merchantRoleId) {
        String sql;
        QyMap params;//删除门店数据库中管理员权限
        sql = "DELETE from merchant_role_permissions where merchant_role_id = :roleId";
        params = QyMap.map("roleId",merchantRoleId);
        branchJdbcTemplate.update(sql,params);
    }

    /**
     * 解绑门店
     * @param merchantId
     * @param merchantGroupId
     */
    void unRelevance(Long merchantId,Long merchantGroupId){
        String sql = "SELECT  count(*) as count from merchants where id = :merchantId and merchant_group_id = :merchantGroupId";
        QyMap map = QyMap.map("merchantId",merchantId).setv("merchantGroupId",merchantGroupId);
        Long count = branchJdbcTemplate.queryForScalar(sql,map,Long.class);
        if(count==0){
            throw new BusinessRunTimeException("解绑失败",10001);
        }

        sql = "update merchants set merchant_group_id = null where id = :merchantId and merchant_group_id = :merchantGroupId";

        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 验证商户 信息 及 密码是否正确
     * @param name
     * @param username
     * @param password
     * @param merchantGroupId
     * @return
     */
    QyMap validateBranch(String name,String username,String password,Long merchantGroupId){
        String sql = "SELECT * from merchant_accounts where is_deleted = 0 and is_admin = 1 and account = :account";
        SqlParameterSource sqlParameterSource=new MapSqlParameterSource("account",username);
        List<Map<String,Object>> list = branchJdbcTemplate.queryForList(sql,sqlParameterSource);
        if(CollectionUtils.isEmpty(list)){
            throw new BusinessRunTimeException("该用户名不存在",10001);
        }
        QyMap accountMap = QyMap.WRAP(list.get(0));


        sql = "SELECT * from merchants where is_deleted = 0 and merchant_group_id = :merchantGroupId and name = :name and id=:merchantId";
        QyMap parames = QyMap.NEW().setv("name",name)
                .setv("merchantGroupId",merchantGroupId)
                .setv("merchantId",accountMap.getLong("merchant_id"));
        list = branchJdbcTemplate.queryForList(sql,parames);
        if(CollectionUtils.isEmpty(list)){
            throw new BusinessRunTimeException("该门店不存在",10002);
        }

        //验证用户名和密码
        String salt = accountMap.getString("salt");
        log.info("salt : {}"+salt);
        String oldPasswordEncrypt = new SimpleHash(algorithmName, password,
                ByteSource.Util.bytes(username+salt),
                hashIterations).toHex();
        log.info("密码 ： {}",oldPasswordEncrypt);
        log.info("原密码 ： {}",accountMap.getString("password_digist"));
        if(oldPasswordEncrypt.equals(accountMap.getString("password_digist"))){
            QyMap map = QyMap.map("phone",list.get(0).get("phone").toString())
                    .setv("merchantId",list.get(0).get("id").toString())
                    .setv("username",username)
                    .setv("name",name);
            return map;
        }
        throw new BusinessRunTimeException("用户名或密码不正确",10001);
    }


    /**
     * //关联门店 将商户组id 跟新到分店
     * @param merchantGroupId
     * @param merchantId
     */
    void updateMerchant(Long merchantGroupId,Long merchantId){
        String sql = "update merchants set merchant_group_id = :merchantGroupId where id = :merchantId";

        QyMap map = QyMap.NEW().setv("merchantGroupId",merchantGroupId)
                .setv("merchantId",merchantId);
        branchJdbcTemplate.update(sql,map);

        //A)物理删除 分店数据库 会员记录（vip_records），
        // 积分兑换明细(vip_point_exchange_details)，
        // 会员卡（member_cards），
        // 会员信息(members)，,
        // 会员卡类型（member_card_types）
        sql = "DELETE from vip_records where merchant_id = :merchantId";
        SqlParameterSource sqlParameterSource=new MapSqlParameterSource("merchantId",merchantId);
        branchJdbcTemplate.update(sql,sqlParameterSource);
        sql = "DELETE from vip_point_exchange_details where merchant_id = :merchantId";
        branchJdbcTemplate.update(sql,sqlParameterSource);
        sql = "DELETE from member_cards where merchant_id = :merchantId";
        branchJdbcTemplate.update(sql,sqlParameterSource);
        sql = "DELETE from members where merchant_id = :merchantId";
        branchJdbcTemplate.update(sql,sqlParameterSource);
        sql = "DELETE from member_card_types where merchant_id = :merchantId";
        branchJdbcTemplate.update(sql,sqlParameterSource);
    }

    /**
     * //验证用户名和密码
     * @param account
     * @param oldPassword
     * @return
     */
    public QyMap validatePassword(String account, String oldPassword) {
        log.info("============== 账号 ： {}",account);
        log.info("============== 密码 ：{} ",oldPassword);
        String sql = "SELECT count(*) as count from merchant_accounts where is_deleted = 0 and is_admin = 1 and account = :account";
        SqlParameterSource sqlParameterSource=new MapSqlParameterSource("account",account);
        Long count = branchJdbcTemplate.queryForScalar(sql,sqlParameterSource,Long.class);
        if(count==0){
            throw new BusinessRunTimeException("账号不存在",10003);
        }
        sql = "SELECT * from merchant_accounts where is_deleted = 0 and is_admin = 1 and account = :account";
        sqlParameterSource=new MapSqlParameterSource("account",account);
        Map<String,Object> map = branchJdbcTemplate.queryForMap(sql,sqlParameterSource);

        log.info("map ------ {}",map);
        if(MapUtils.isEmpty(map)){
            throw new BusinessRunTimeException("该账号不存在",10001);
        }
        QyMap accountMap = QyMap.WRAP(map);
        Long merchantId = accountMap.getLong("merchant_id");
        if (merchantId==null){
            throw new BusinessRunTimeException("该商户不存在",10002);
        }
        sql = "SELECT id,account_id,accountant,address,district,name,phone,linker,industry,tel_phone from merchants where id = :merchantId";
        sqlParameterSource = new MapSqlParameterSource("merchantId",merchantId);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,sqlParameterSource);
        if(CollectionUtils.isEmpty(mapList)){
            throw new BusinessRunTimeException("该商户不存在",10002);
        }
        QyMap merchantMap = QyMap.WRAP(mapList.get(0));
        if(MapUtils.isEmpty(merchantMap)){
            throw new BusinessRunTimeException("该商户不存在",10002);
        }
        long merchantGroupId = merchantMap.getLong("merchant_group_id");
        log.info("merchantMap ： {}",merchantMap);
        log.info("merchantGroupId ： {}",merchantMap.getLong("merchant_group_id"));
        if(merchantMap.getLong("merchant_group_id")!=-1){
            throw new BusinessRunTimeException("该商户已绑定过",10003);
        }
        //验证密码
        String salt = accountMap.getString("salt");
        log.info("salt : {}"+salt);
        String oldPasswordEncrypt = new SimpleHash(algorithmName, oldPassword,
                ByteSource.Util.bytes(account+salt),
                hashIterations).toHex();
        log.info("密码 ： {}",oldPasswordEncrypt);
        log.info("原密码 ： {}",accountMap.getString("password_digist"));
        if(oldPasswordEncrypt.equals(accountMap.getString("password_digist"))){
            merchantMap.setv("account",accountMap.getString("account"));
            return merchantMap;
        }
        throw new BusinessRunTimeException("用户名或密码不正确",10001);
    }

    /**
     * 初始化数据
     * @param branch
     * @param keyMap
     * @param password
     * @return
     */
    public Long initData(Branch branch, QyMap keyMap,String password) {
        //添加商戶
        String sql = "INSERT INTO merchants (create_at,is_deleted,status,access_key,accountant,address,name,phone,secret_key,reg_key,dealer_id,district,merchant_group_id)\n" +
                "VALUES(NOW(),0,0,:accessKey,'01:00',:address,:name,:phone,:secretKey,:regKey,:dealerId,:district,:merchantGroupId)";

        QyMap params= QyMap.map("accessKey", RandomStringUtils.random(32, true, true))
                .setv("name", branch.getName())
                .setv("address",branch.getAddress())
                .setv("phone",branch.getPhone())
                .setv("secretKey", DigestUtils.sha1Hex(UUID.randomUUID().toString()))
                .setv("regKey", keyMap.getLong("regId"))
                .setv("dealerId",keyMap.getLong("dealerId"))
                .setv("district",branch.getLocation())
                .setv("merchantGroupId",branch.getMerchantGroupId());
        Long merchantId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
        log.info(">>>>>>>>>>>>>>>>>>>> 商户id : {}",merchantId);

        //查询账号是否存在
        sql = "SELECT * from merchant_accounts where is_deleted=0 and is_admin = 1 and account = :account";
        params = QyMap.NEW().setv("account",branch.getUsername());
        List<Map<String,Object>> list = branchJdbcTemplate.queryForList(sql,params);
        log.info("账号 ：{}  "+branch.getUsername());
        log.info("list >>>> : {}",list);
        if(CollectionUtils.isNotEmpty(list) || list.size()>0){
            throw new BusinessRunTimeException("该账号已存在",10001);
        }
        //添加账号
        sql = "INSERT into merchant_accounts(create_at,is_deleted,status,account,check_success,locked,password_digist,salt,is_admin,merchant_id,real_name)\n" +
                "VALUES(NOW(),0,0,:account,1,0,:passwordDigist,:salt,1,:merchantId,:realName)";
        QyMap passworddigist = getPasswordDigist(branch.getUsername(),password);
        params = QyMap.NEW().setv("account",branch.getUsername())
                .setv("passwordDigist",passworddigist.getString("newPassword"))
                .setv("salt",passworddigist.getString("salt"))
                .setv("merchantId",merchantId)
                .setv("realName",branch.getUsername());
        Long accountId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
        log.info(">>>>>>>>>>>>>>>>>>>> 账号id : {}",accountId);
        //更新商户账号和appid
        if(merchantId!=null && accountId!=null){
            sql = "update merchants set app_id = :merchantId,account_id = :accountId where id = :merchantId";
            params = QyMap.NEW();
            params.setv("merchantId",merchantId);
            params.setv("accountId",accountId);
            branchJdbcTemplate.update(sql,params);
        }else {
            throw new BusinessRunTimeException("添加失败",10003);
        }


       /* //创建一个管理员角色
        sql = "INSERT into merchant_roles(CREATE,is_deleted,status,code,delete_able,name,merchant_id)\n" +
                "VALUES(NOW(),0,0,:code,1,:name,:merchantId)";
        params = QyMap.NEW().setv("code", ManagementRole.ADMINISTRATOR_CODE)
        .setv("name","超级管理员");
        branchJdbcTemplate.insertForAutoIncrement(sql,params);*/


        //员工分组
        /*sql = "SELECT count(*) as count from cashier_groups where merchant_id = :merchantId";
        params = QyMap.map("merchantId",merchantId);
        Long count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        QyMap map = QyMap.NEW();
        if(count.intValue()==0){
            //角色  管理员 / 经理 / 收银员 / 服务员
            //============================================================
            //管理员 isadmin = true
            sql = "INSERT into merchant_roles(create_at,is_deleted,status,code,delete_able,name,merchant_id)\n" +
                    "VALUES(NOW(),0,0,:code,1,:name,:merchantId)";
            params = QyMap.NEW().setv("code", "merchant_"+RandomStringUtils.random(32, true, true))
                    .setv("name","管理员")
                    .setv("merchantId",merchantId);
            Long roleId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("adminRole",roleId);//管理员角色id



            //经理
            params = QyMap.NEW().setv("code","merchant_"+RandomStringUtils.random(32, true, true))
                    .setv("name","经理")
                    .setv("merchantId",merchantId);
            roleId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("jingliRoleId",roleId);


            //收银员
            params = QyMap.NEW().setv("code","merchant_"+RandomStringUtils.random(32, true, true))
                    .setv("name","收银员")
                    .setv("merchantId",merchantId);
            roleId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("shouYinYuanRoleId",roleId);

            //服务员
            params = QyMap.NEW().setv("code","merchant_"+RandomStringUtils.random(32, true, true))
                    .setv("name","服务员")
                    .setv("merchantId",merchantId);
            roleId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("fuWuYuanRoleId",roleId);

            //============================================================

            //创建分组
            //管理员
            sql = "INSERT INTO cashier_groups (create_at,is_deleted,status,merchant_id,is_admin,discount_limit,erase_limit,name,role_id,is_def) " +
                    " VALUES(NOW(),0,0,:merchantId,:isAdmin,0,0,:name,:roleId,1)";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("isAdmin",1)
                    .setv("name","管理员")
                    .setv("roleId",map.getLong("adminRole"));
            Long groupId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("adminGroupId",groupId);

            //经理
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("isAdmin",0)
                    .setv("name","经理")
                    .setv("roleId",map.getLong("jingliRoleId"));
            groupId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("jingliGroupId",groupId);

            //收银员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("isAdmin",0)
                    .setv("name","收银员")
                    .setv("roleId",map.getLong("shouYinYuanRoleId"));
            groupId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("shouYinYuanGroupId",groupId);

            //服务员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("isAdmin",0)
                    .setv("name","服务员")
                    .setv("roleId",map.getLong("fuWuYuanRoleId"));
            groupId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("fuWuYuanGroupId",groupId);

            //============================================================

            //账号 四个员工账号 0000,0001,0002,0003,0004
            // 0000
            sql = "INSERT into merchant_accounts(create_at,is_deleted,status,account,check_success,locked,password_digist,salt,is_admin,merchant_id,real_name)\n" +
                    "VALUES(NOW(),0,0,:account,1,0,:passwordDigist,:salt,0,:merchantId,:realName)";
            passworddigist = getPasswordDigist("0000",password);
            params = QyMap.NEW().setv("account","0000")
                    .setv("passwordDigist",passworddigist.getString("newPassword"))
                    .setv("salt",passworddigist.getString("salt"))
                    .setv("merchantId",merchantId)
                    .setv("realName","0000");
            Long acc_id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("acc_id_0000",acc_id);

            // 0001
            passworddigist = getPasswordDigist("0001",password);
            params = QyMap.NEW().setv("account","0001")
                    .setv("passwordDigist",passworddigist.getString("newPassword"))
                    .setv("salt",passworddigist.getString("salt"))
                    .setv("merchantId",merchantId)
                    .setv("realName","0001");
            acc_id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("acc_id_0001",acc_id);

            // 0002
            passworddigist = getPasswordDigist("0002",password);
            params = QyMap.NEW().setv("account","0002")
                    .setv("passwordDigist",passworddigist.getString("newPassword"))
                    .setv("salt",passworddigist.getString("salt"))
                    .setv("merchantId",merchantId)
                    .setv("realName","0002");
            acc_id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("acc_id_0002",acc_id);

            // 0003
            passworddigist = getPasswordDigist("0003",password);
            params = QyMap.NEW().setv("account","0003")
                    .setv("passwordDigist",passworddigist.getString("newPassword"))
                    .setv("salt",passworddigist.getString("salt"))
                    .setv("merchantId",merchantId)
                    .setv("realName","0003");
            acc_id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("acc_id_0003",acc_id);

            // 0004
            passworddigist = getPasswordDigist("0004",password);
            params = QyMap.NEW().setv("account","0004")
                    .setv("passwordDigist",passworddigist.getString("newPassword"))
                    .setv("salt",passworddigist.getString("salt"))
                    .setv("merchantId",merchantId)
                    .setv("realName","0004");
            acc_id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("acc_id_0004",acc_id);

            //============================================================

            //创建员工
            //员工 四个 0000,0001,0002,0003,0004

            sql = "INSERT into cashiers(create_at,is_deleted,status,merchant_id,gender,name,state,account_id,group_id)\n" +
                    "VALUES(NOW(),0,0,:merchantId,'MAN',:name,'NORMAL',:accountId,:groupId)";

            //管理员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name",branch.getUsername())
                    .setv("accountId",accountId)
                    .setv("groupId",map.getLong("adminGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            // 0000 经理
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","0000")
                    .setv("accountId",map.getLong("acc_id_0000"))
                    .setv("groupId",map.getLong("jingliGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            // 0001 收银员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","0001")
                    .setv("accountId",map.getLong("acc_id_0001"))
                    .setv("groupId",map.getLong("shouYinYuanGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            // 0002 服务员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","0002")
                    .setv("accountId",map.getLong("acc_id_0002"))
                    .setv("groupId",map.getLong("shouYinYuanGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            // 0003 服务员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","0003")
                    .setv("accountId",map.getLong("acc_id_0003"))
                    .setv("groupId",map.getLong("fuWuYuanGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            // 0004 服务员
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","0004")
                    .setv("accountId",map.getLong("acc_id_0004"))
                    .setv("groupId",map.getLong("fuWuYuanGroupId"));
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

        }
        //============================================================

        //营业时间
        sql = "SELECT count(*) as count from merchant_business_hours where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            //营业时间添加  上午09:00 到 14:00
            //下午 14:00 到 24:00
            sql = "INSERT into merchant_business_hours(create_at,is_deleted,status,merchant_id,end_time,name,start_time)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:endTime,:name,:startTime)";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","上午")
                    .setv("endTime","14:00")
                    .setv("startTime","09:00");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","下午")
                    .setv("endTime","24:00")
                    .setv("startTime","14:00");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

        }
        //============================================================

        //餐台
        sql = "SELECT count(*) as count from dining_table_regions where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            //餐台区
            sql = "INSERT into dining_table_regions(create_at,is_deleted,status,merchant_id,commission,commission_type,commission_value,name,seatingnum,type)\n" +
                    "VALUES(NOW(),0,0,:merchantId,0,'PROPROTIONADD',0,:name,20,:type)";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","一楼").setv("type","NORMAL");
            Long cantaiId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("one",cantaiId);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","二楼").setv("type","NORMAL");
            cantaiId = branchJdbcTemplate.insertForAutoIncrement(sql,params);
            map.setv("two",cantaiId);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","自动生成").setv("type","AUTO");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","联台区").setv("type","JOINT");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","反结区").setv("type","ANTIKNOT");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            //餐台
            sql = "INSERT INTO dining_tables(create_at,is_deleted,status,merchant_id,commission,commission_type,commission_value,lobby,name,no,seatingnum,state,range_id)\n" +
                    "VALUES(now(),0,0,:merchant_id,0,'FIXEDADD',0,0,:name,:no,4,'NOOPENED',:rangeId)";
            Map<String,?>[] pars=new Map[10];
            for (int i=0;i<10;i++){
                pars[i]=ImmutableMap.of(
                        "merchant_id",merchantId,
                        "name","0"+i,
                        "no","0"+i,
                        "rangeId",i<5?map.getLong("one"):map.getLong("two")
                );
            }
            branchJdbcTemplate.batchUpdate(sql,pars);

        }

        //============================================================
        //原因备注
        sql = "SELECT count(*) as count from comments where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO comments (create_at,is_deleted,status,merchant_id,name,type)\n" +
                    "values(NOW(),0,0,:merchantId,:name,'TASTE')";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","不放辣");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","少放盐");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","不要香菜");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);
        }

        //============================================================

        //菜品单位
        sql = "SELECT count(*) as count from dishes_units where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO dishes_units(create_at,is_deleted,status,merchant_id,name,no,state)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:name,:no,'NORMAL')";
            String [] units = {
                    "斤","份","片","对","提","块","支","套","卷","付","听","捆","根","桶","张","盘",
                    "个","条","件","双","碗","升","毫升","瓶","串","盒","板","克","袋"
            };
            Map<String,?>[] pars=new Map[units.length];
            for (int i=0;i<units.length;i++){
                pars[i]=ImmutableMap.of(
                        "merchantId",merchantId,
                        "name",units[i],
                        "no", StringUtils.leftPad((i+1)+"", 3, "0")
                );
            }
            branchJdbcTemplate.batchUpdate(sql,pars);

        }

        //============================================================
        //原料单位
        sql = "SELECT count(*) as count from material_units where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO material_units(create_at,is_deleted,status,merchant_id,name,no,state)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:name,:no,'NORMAL')";

            String [] units = {
                    "斤","袋","克","箱","板","盒","串","瓶","毫升","升","双","件","条","个","张",
                    "桶","根","包","捆","听","付","卷","支","把","台","米","平米","本","块","千克",
                    "提","对","床","片","份",
            };

            Map<String,?>[] pars=new Map[units.length];
            for (int i=0;i<units.length;i++){
                pars[i]=ImmutableMap.of(
                        "merchantId",merchantId,
                        "name",units[i],
                        "no", StringUtils.leftPad((i+1)+"", 3, "0")
                );
            }
            branchJdbcTemplate.batchUpdate(sql,pars);
        }

        //============================================================

        //菜品分类
        sql = "SELECT count(*) as count from material_units where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO dishes_categorys(create_at,is_deleted,status,merchant_id,is_package,name,no,state)\n" +
                    "VALUES(NOW(),0,0,:merchantId,0,:name,:no,'NORMAL')";
            String [] taocan = {
                    "套餐","凉菜","热菜"
            };
            Map<String,?>[] pars=new Map[taocan.length];
            for (int i=0;i<taocan.length;i++){
                pars[i]=ImmutableMap.of(
                        "merchantId",merchantId,
                        "name",taocan[i],
                        "no", StringUtils.leftPad((i+1)+"", 5, "0")
                );
            }
            branchJdbcTemplate.batchUpdate(sql,pars);

        }
        //============================================================
        //支付方式
        sql = "SELECT count(*) as count from payment_types where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO payment_types(create_at,is_deleted,status,merchant_id,delete_able,has_point,name,state,type,remark)\n" +
                    "VALUES(NOW(),0,0,:merchantId,0,1,:name,'NORMAL',:type,'默认支付方式，不可删除')";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","现金支付")
                    .setv("type","CASH");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","挂账支付")
                    .setv("type","SUSPENDED");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","会员支付")
                    .setv("type","MEMBER");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

        }
        //============================================================
        //打印大类
        sql = "SELECT count(*) as count from printer_categorys where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO printer_categorys(create_at,is_deleted,status,merchant_id,name,no,state)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:name,:no,'NORMAL')";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","默认大类")
                    .setv("no","0001");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);
        }
        //============================================================
        //初始化商户系统设置
        sql = "SELECT count(*) as count from printer_categorys where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT into merchant_settings(create_at,is_deleted,status,merchant_id,name,type,value)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:name,:type,:value)";

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","经营模式")
                    .setv("type","REPAST_MODE")
                    .setv("value","CHINESE_FOOD");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","门店名称")
                    .setv("type","SHOP_NAME")
                    .setv("value","CHINESE_FOOD");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","同步菜品到原料")
                    .setv("type","SYNC_DISHES")
                    .setv("value","CHINESE_FOOD");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

        }
        //============================================================
        //增加默认仓库
        sql = "SELECT count(*) as count from warehouses where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT into warehouses(create_at,is_deleted,status,merchant_id,name,no,state)\n" +
                    "VALUES(now(),0,0,:merchantId,:name,:no,'NORMAL')";
            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","默认仓库")
                    .setv("no","S001");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);
        }
        //============================================================
        //序列号 单号 流水号 班次号
        sql = "SELECT count(*) as count from warehouses where merchant_id = :merchantId";
        params = QyMap.NEW().setv("merchantId",merchantId);
        count = branchJdbcTemplate.queryForScalar(sql,params,Long.class);
        if(count==0){
            sql = "INSERT INTO serial_numbers(create_at,is_deleted,status,merchant_id,name,no,type)\n" +
                    "VALUES(NOW(),0,0,:merchantId,:name,:no,:type)";

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","账单编号")
                    .setv("no","100000000")
                    .setv("type","BILL_NO");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","班次序号")
                    .setv("no","0")
                    .setv("type","SHIFT_NO");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","流水号")
                    .setv("no","10000")
                    .setv("type","ORDER_FLOW_NO");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);

            params = QyMap.NEW().setv("merchantId",merchantId)
                    .setv("name","订单编号")
                    .setv("no","1000000")
                    .setv("type","ORDER_NO");
            branchJdbcTemplate.insertForAutoIncrement(sql,params);
        }*/

        return merchantId;

    }
    private String algorithmName = "md5";
    private final int hashIterations = 2;

    /**
     * encryptPassword:加密明文密码 <br/>
     * @author wuqing
     * @param account
     * @since JDK 1.7
     */
    private QyMap getPasswordDigist(String account,String password) {
        String salt=randomNumberGenerator.nextBytes().toHex();
        String newPassword = encryptPassword(password,account+salt);
        return QyMap.map("salt",salt).setv("newPassword",newPassword);
    }

    /**
     * encryptPassword:加密明文密码. <br/>
     * @author wuqing
     * @param password 明文密码
     * @param salt 盐值
     * @return
     * @since JDK 1.7
     */
    private String encryptPassword(String password,String salt){
        return new SimpleHash(algorithmName, password,
                ByteSource.Util.bytes(salt),
                hashIterations).toHex();
    }

}